#include "ServerChannel.h"
#include "Selector.h"

#include <assert.h>

namespace nio {

	ServerChannel::ServerChannel(ChannelDelegate* delegate) {
		this->delegate = delegate;
		this->eventLoop = new EventLoop();
		this->eventLoop->startup();
	}

	ServerChannel::~ServerChannel() {
		eventLoop->shutdown();
		delete eventLoop;
		eventLoop = nullptr;
	}

	void ServerChannel::startServer(std::string ip, int port) {
		socket = new Socket(SocketFamily::inet, SocketType::stream);
		socket->ReuseAddr(true);
		socket->SetNonblocking(true);
		socket->Bind(ip.c_str(), port);
		socket->Listen();
		eventLoop->selector.addEvents(this, EventSetRead | EventSetExcept);
	}

	void ServerChannel::stopServer() {
		eventLoop->selector.clearEvents(this);
		socket->Close();
		socket = nullptr;
	}


	SOCKET ServerChannel::getFD() {
		if (socket == nullptr)return INVALID_FD;
		return socket->getfd();
	}

	void ServerChannel::onEvents(int events) {
		if (events & EventSetRead) {
			onAcceptable();
		}
		if (events & EventSetExcept) {
			SocketError err("Server exception", Errno);
			onError(&err);
		}
	}


	void ServerChannel::onAcceptable() {
		auto newSocket = socket->Accept();
		if (newSocket == nullptr)return;
		auto newClient = new ClientChannel(delegate, eventLoop, newSocket);
		eventLoop->selector.addEvents(newClient, EventSetRead | EventSetWrite);
		if (delegate != nullptr) {
			delegate->onAccept(newClient);
		}
	}

	void ServerChannel::onError(SocketError* error) {
		if (delegate != nullptr) {
			delegate->onError(error);
		}
	}

}